package editorsvg.editor.formas;

import editorsvg.editor.atributos.AtrString;
import editorsvg.editor.documento.PrototipoElemento;
import editorsvg.propiedades.GrupoPropiedades;
import editorsvg.propiedades.PropiedadTextoMultilinea;
import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import org.apache.batik.parser.DefaultPointsHandler;
import org.apache.batik.parser.ParseException;
import org.apache.batik.parser.PointsHandler;
import org.apache.batik.parser.PointsParser;

/**
 * Forma que representa una polilinea.
 * @author Jorge Berjano
 */
public class Polilinea extends Forma {

    private AtrString puntos = new AtrString();
    private int numeroPuntos;
//    protected LinkedList<Point2D> nodos = new LinkedList<Point2D>();
    protected Path2D path = new Path2D.Double();
    private Point2D nodoSiguiente;
    private static GrupoPropiedades grupoPropiedades;    

    @Override
    public String getNombreTag() {
        return PrototipoElemento.polyline.name();
    }

    /**
     * Obtiene el número de nodos de la polilinea.
     */
    public int getNumeroPuntos() {
        return numeroPuntos;
    }

    @Override
    public Shape getShape() {
        if (nodoSiguiente != null) {
            Path2D pathActual;
            pathActual = (Path2D) path.clone();
            pathActual.lineTo(nodoSiguiente.getX(), nodoSiguiente.getY());
            return pathActual;
        } else {
            return path;
        }
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        Polilinea clon = (Polilinea) super.clone();
        clon.puntos = (AtrString) puntos.clone();
//        clon.nodos = (LinkedList<Point2D>) nodos.clone();
        clon.path = (Path2D) path.clone();
        return clon;
    }

    @Override
    public GrupoPropiedades getPropiedades() {
        if (grupoPropiedades == null) {
            grupoPropiedades = new GrupoPropiedades("Polilinea");
            grupoPropiedades.agregarPropiedad(new PropiedadTextoMultilinea("puntos", "points"));
        }
        return grupoPropiedades;
    }

    /**
     * Agrega una posicion al atributo que contiene los puntos de la polilinea.
     * @param posicion Posición cuyas coordenadas se van a agregar.
     */
    private void agregarAPuntos(Point2D posicion) {
        String texto = puntos.getTexto();
        puntos.setValor((texto == null ? "" : texto) + posicion.getX() + "," + posicion.getY() + "\n");
        numeroPuntos++;
    }

    /**
     * Indica la posición inicial de la polilinea.
     * @param posicion
     */
    public void iniciar(Point2D posicion) {
//        nodos.add(posicion);
        path.reset();
        path.moveTo(posicion.getX(), posicion.getY());
        agregarAPuntos(posicion);
        nodoSiguiente = (Point2D) posicion.clone();

    }

    public void agregarNodo(Point2D posicion) {
        if (nodoSiguiente != null) {
            nodoSiguiente.setLocation(posicion);
            path.lineTo(posicion.getX(), posicion.getY());
            agregarAPuntos(nodoSiguiente);
        }
    }

    public void siguientePosicion(Point2D posicion) {
        nodoSiguiente.setLocation(posicion);
    }

    public void finalizar() {
        //nodos.add(nodoSiguiente);
        agregarAPuntos(nodoSiguiente);
    }

    @Override
    public void actualizar() {
        parsearPuntos();
//        generarPath();
    }

    public AtrString puntos() {
        return puntos;
    }

    public String getPuntos() {
        return puntos.getValor();
    }

    public void setPuntos(String valor) {
        puntos.setValor(valor);
    }

    /**
     * Parsea el atributo puntos generando la lista de nodos.
     */
    protected void parsearPuntos() {
        numeroPuntos = 0;
        try {
            path.reset();
            if (puntos.getTexto() == null) {
                return;
            }

            PointsParser parser = new PointsParser();
            PointsHandler handler = new DefaultPointsHandler() {

                @Override
                public void point(float x, float y) throws ParseException {
                    if (numeroPuntos == 0) {
                        path.moveTo(x, y);
                    } else {
                        path.lineTo(x, y);
                    }
                    numeroPuntos++;                    
                }
            };
            parser.setPointsHandler(handler);
            parser.parse(puntos.getTexto());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

//    protected void generarPath() {
//        path.reset();
//        for (Point2D nodo : nodos) {
//            if (nodo == nodos.get(0)) {
//                path.moveTo(nodo.getX(), nodo.getY());
//            } else {
//                path.lineTo(nodo.getX(), nodo.getY());
//            }
//        }
//    }
}
